#pragma once
#include <string>
#include <iostream>

/*
 *
 */
#ifdef DEBUG
#define DEBUG_ASSERT(condition) {                \
        if (!(condition)) {                 \
            std::string msg("DEBUG_ASSERT fails.");      \
			cout<<msg<<endl;					\
			throw msg;		\
		}                                   \
}
#define MDEBUG_ASSERT(condition, msg) {        \
    if (!(condition)) {\
        std::string str_msg = msg;      \
        cout<<"MDEBUG_ASSERT: "<<str_msg<<endl;					\
        throw str_msg;      \
    }                                   \
}
#else
#define DEBUG_ASSERT(condition)
#define MDEBUG_ASSERT(condition)
#endif

/*
 * Release assertions, would not be exlcluded with debug code.
 */

#define ASSERT(condition) {                 \
    if (!(condition)) {                     \
        std::string msg("ASSERT fails.");   \
        cout<<msg<<endl;					\
        throw msg;                          \
    }                                       \
}
#define MASSERT(condition, msg) {                 \
    if (!(condition)) {\
        std::string str_msg = msg;      \
        cout<<"MASSERT: "<<str_msg<<endl;					\
        throw str_msg;      \
    }                                   \
}

/*
 * Assertions fo static expressions.
 */
template <bool> class StaticAssert;
template <> class StaticAssert<true> {};

//template <typename > class ErrorChecker;

#define SASSERT(expr) { \
	enum {\
		TEST = sizeof(StaticAssert<(expr) != 0 >)\
	};\
}

/*
 *
 */
#define MSDEBUG_ASSERT(expr, msg) {                \
	class ERROR_##msg;                      \
    (void)sizeof(                           \
        CompileTimeChecker<(expr) != 0 >(   \
            ERROR_##msg()                   \
        )                                   \
    )                                       \
}
